package cn.ac.big.bigd.transfer;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
public class FileCopy {
    private static final int BUFFER_SIZE_1024 = 1024;
    private static final int BUFFER_SIZE_4096 = 4096;
    private static final int BUFFER_SIZE_10240 = 10240;
        
    private static final String FROM_FILE_42MB = "E:/work/projects/SRA/testfiles/test.fastq";
    private static final String FROM_FILE_1GB = "E:/work/projects/SRA/testfiles/demo_bsseq_reads1.txt.tar.gz";
        
    private static int BUFFER_SIZE = BUFFER_SIZE_1024;
    private static String FROM_FILE = FROM_FILE_42MB;
    /**
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
//        System.out.println("File :" + FROM_FILE + " ---- Buffer Size : " + BUFFER_SIZE + "--------------");
//        testFileCopy();
//            
//        BUFFER_SIZE = BUFFER_SIZE_4096;
//        System.out.println("File :" + FROM_FILE + " ---- Buffer Size : " + BUFFER_SIZE + "--------------");
//        testFileCopy();
//            
//        BUFFER_SIZE = BUFFER_SIZE_10240;
//        System.out.println("File :" + FROM_FILE + " ---- Buffer Size : " + BUFFER_SIZE + "--------------");
//        testFileCopy();
            
        BUFFER_SIZE = BUFFER_SIZE_1024;
        FROM_FILE = FROM_FILE_1GB;
        System.out.println("File :" + FROM_FILE + " ---- Buffer Size : " + BUFFER_SIZE + "--------------");
        testFileCopy();
            
        BUFFER_SIZE = BUFFER_SIZE_4096;
        FROM_FILE = FROM_FILE_1GB;
        System.out.println("File :" + FROM_FILE + " ---- Buffer Size : " + BUFFER_SIZE + "--------------");
        testFileCopy();
            
        BUFFER_SIZE = BUFFER_SIZE_10240;
        FROM_FILE = FROM_FILE_1GB;
        System.out.println("File :" + FROM_FILE + " ---- Buffer Size : " + BUFFER_SIZE + "--------------");
        testFileCopy();
            
    }
    private static void testFileCopy() throws FileNotFoundException,
            IOException {
        coypByMbb();
        copyByNioTransferFrom();
        copyByNioTransferTo();
        TransByNioFileChannelCommon();
        coypByBufferRead();
        coypByFastBufferRead();           
        coypByStream();//Old IO style
    }
    /**
     * ʹ��FileChannel.transferFrom()ʵ��
     * @throws FileNotFoundException
     * @throws IOException
     */
    private static void copyByNioTransferFrom() throws FileNotFoundException,
            IOException {
        long startTime = System.currentTimeMillis();
        RandomAccessFile fromFile = new RandomAccessFile(FROM_FILE, "rw");
        FileChannel fromChannel = fromFile.getChannel();
        RandomAccessFile toFile = new RandomAccessFile("E:/work/projects/SRA/testfiles/to1.tar.gz", "rw");
        FileChannel toChannel = toFile.getChannel();
        long position = 0;
        long count = fromChannel.size();
        toChannel.transferFrom(fromChannel, position, count);
        long endTime = System.currentTimeMillis();
        System.out.println("copyByNioTransferFrom time consumed(buffer size no effect) : "
                + (endTime - startTime));
    }
    /**
     * ʹ��FileChannel.transferTo()ʵ��
     * @throws FileNotFoundException
     * @throws IOException
     */
    private static void copyByNioTransferTo() throws FileNotFoundException,
            IOException {
        long startTime = System.currentTimeMillis();
        RandomAccessFile fromFile = new RandomAccessFile(FROM_FILE, "rw");
        FileChannel fromChannel = fromFile.getChannel();
        RandomAccessFile toFile = new RandomAccessFile("E:/work/projects/SRA/testfiles/to2.tar.gz", "rw");
        FileChannel toChannel = toFile.getChannel();
        long position = 0;
        long count = fromChannel.size();
        fromChannel.transferTo(position, count, toChannel);
        long endTime = System.currentTimeMillis();
        System.out.println("copyByNioTransferTo time consumed(buffer size no effect) : "
                + (endTime - startTime));
    }
    /**
     * ʹ��Channel, Buffer�򵥶�дʵ��
     * @throws IOException
     */
    private static void coypByBufferRead() throws IOException {
        long startTime = System.currentTimeMillis();
        FileInputStream fin = new FileInputStream(FROM_FILE);
        FileOutputStream fout = new FileOutputStream("E:/work/projects/SRA/testfiles/to3.tar.gz");
        FileChannel fcin = fin.getChannel();
        FileChannel fcout = fout.getChannel();
        ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
        while (true) {
            buffer.clear();
            int r = fcin.read(buffer);
            if (r == -1) {
                break;
            }
            buffer.flip();
            fcout.write(buffer);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("coypByBufferRead time consumed(buffer size take effect) : "
                + (endTime - startTime));
    }
    /**
     * @throws IOException
     */
    private static void coypByFastBufferRead() throws IOException {
        long startTime = System.currentTimeMillis();
        FileInputStream fin = new FileInputStream(FROM_FILE);
        FileOutputStream fout = new FileOutputStream("E:/work/projects/SRA/testfiles/to4.tar.gz");
        FileChannel fcin = fin.getChannel();
        FileChannel fcout = fout.getChannel();
        ByteBuffer buffer = ByteBuffer.allocateDirect(BUFFER_SIZE);
        while (true) {
            buffer.clear();
            int r = fcin.read(buffer);
            if (r == -1) {
                break;
            }
            buffer.flip();
            fcout.write(buffer);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("coypByFastBufferRead time consumed(buffer size take effect) : "
                + (endTime - startTime));
    }
    /**
     * @throws IOException
     */
    private static void coypByMbb() throws IOException {
        long startTime = System.currentTimeMillis();
        FileInputStream fin = new FileInputStream(FROM_FILE);
        RandomAccessFile fout = new RandomAccessFile("E:/work/projects/SRA/testfiles/to5.tar.gz", "rw");
        FileChannel fcin = fin.getChannel();
        FileChannel fcout = fout.getChannel();
        MappedByteBuffer mbbi = fcin.map(FileChannel.MapMode.READ_ONLY, 0,
                fcin.size());
        MappedByteBuffer mbbo = fcout.map(FileChannel.MapMode.READ_WRITE, 0,
                fcin.size());
        mbbo.put(mbbi);
        mbbi.clear();
        mbbo.clear();
        long endTime = System.currentTimeMillis();
        System.out
                .println("coypByMbb time consumed(buffer size no effect) : " + (endTime - startTime));
    }
    
    /**
     * NIO and buffer*/
    public static void TransByNioFileChannelCommon() throws IOException {
    	 
        long beginTime = System.currentTimeMillis();
 
        FileChannel fc = new FileInputStream(new File(FROM_FILE)).getChannel();
 
        FileChannel fco = new RandomAccessFile(new File("E:/work/projects/SRA/testfiles/to7.tar.gz"), "rw")
                .getChannel();
 
        ByteBuffer buf = ByteBuffer.allocate(1024);
 
        while (fc.read(buf) != -1) {
            buf.flip();
            fco.write(buf);
            buf.clear();
        }
 
        long endTime = System.currentTimeMillis();
 
        System.out.println("NIO FileChannel"
                + (endTime - beginTime));
    }
 
    /**
     * ʹ�ô�ͳIO������д��ʽʵ��
     * @throws IOException
     */
    private static void coypByStream() throws IOException {
        long startTime = System.currentTimeMillis();
        FileInputStream fin = new FileInputStream(FROM_FILE);
        FileOutputStream fout = new FileOutputStream("E:/work/projects/SRA/testfiles/to6.tar.gz");
        byte[] buffer = new byte[BUFFER_SIZE];
        while (true) {
            int ins = fin.read(buffer);
            if (ins == -1) {
                fin.close();
                fout.flush();
                fout.close();
                break;
            } else{
                fout.write(buffer, 0, ins);
            }             
        }
        long endTime = System.currentTimeMillis();
        System.out.println("coypByStream time consumed(buffer size take effect) : " + (endTime - startTime));
    }
}
